package EMM;

import java.util.Comparator;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;

public class DependencyCheckerImpl implements DependencyChecker {
	
	public static Comparator g_bundleIdComparator = new BundleIdComparator();

	private ServiceReference 	_svcRef			=	null;
	private BundleContext		_bundleContext	=	null;
	private	Bundle[]			_bundles		=	null;
	
	// Constructor
	public DependencyCheckerImpl(BundleContext bc)
	{
		_bundleContext	=	bc;
	}
	////////////////////////////////////////////////
    static public Set getPackageClosure(PackageAdmin pkgAdmin,
			Bundle[]     allBundles,
			Bundle       target,
			Set          handled) 
    {
    	if ( pkgAdmin	==	null ) return null;
    	if ( handled	==	null )
    		handled = new HashSet();

    	Set closure	=	new TreeSet( g_bundleIdComparator );

    	for( int i = 0;  i < allBundles.length ; i++) {
    		ExportedPackage[] pkgs	=	pkgAdmin.getExportedPackages( allBundles[i] );

    		for( int j = 0 ; pkgs != null && j < pkgs.length ; j++ ) {
    			Bundle[] blz	=	pkgs[j].getImportingBundles();

    			for( int k = 0 ; blz != null && k < blz.length ; k++ ){
    				if( blz[k].getBundleId() == target.getBundleId() ) {
    					closure.add( allBundles[i] );

    					if( handled.contains( allBundles[i] )) {
    						handled.add( allBundles[i] );

    						Set trans = getPackageClosure( pkgAdmin, allBundles, allBundles[i], handled );
    						closure.addAll(trans);
    						}
    					}
    				}
    			}
    		}	
    	return closure;
    }
	

	public String[] Analyze(Bundle bundle) {
	
		Bundle[]	bundles	=	null;
		
		bundles	= new Bundle[1];
		bundles[0]	=	bundle;
		
		return Analyze(bundles);
	}
	
    public String[] Analyze(Bundle[] bundles) {
		
		_svcRef	=	_bundleContext.getServiceReference(PackageAdmin.class.getName() );
		PackageAdmin pkgAdmin =  (PackageAdmin) _bundleContext.getService(_svcRef);
		
		if ( pkgAdmin == null ) return null;
		
		Bundle[] 	bls 		= 	getBundleArray();
		Set 		pkgClosure	=	new TreeSet( g_bundleIdComparator );
		
		// for test
		System.out.println(" Checking bundles....");
		//
		for( int i = 0; i < bundles.length ; i++)
		{
			//for test
			//Dictionary dic	=	bundles[i].getHeaders();
			String strTmp	=	(String) bundles[i].getHeaders("Bundle-Name").toString();
			System.out.println("Check Bundle Name : " + strTmp );
			//
			Set ret = getPackageClosure( pkgAdmin, bls, bundles[i], null);
			pkgClosure.addAll( ret );
		}
		
		if( pkgClosure.size() != 0 )
		{
			for( java.util.Iterator itr = pkgClosure.iterator() ; itr.hasNext(); ) {
				Bundle depBundle 	= (Bundle) itr.next();
//				String strDepBundle = (String) depBundle.getHeaders("Bundle-Name");
				
				Dictionary 	dicDepbundle 	= depBundle.getHeaders();
				String 		strDep 			= dicDepbundle.get("Bundle-Name").toString();
			
				
				System.out.println( strDep ); 
			}
		}
		//System.out.println( pkgClosure.toString() );
		
		return null;
	}
	
    static String GetBundleName(Bundle bundle){
    	String	strRet	=	null;
    	
    	strRet	=	getHeader( bundle, "Bundle-Name" , "" );
    	if( strRet == null || "".equals( strRet ) || strRet.startsWith( "%" ) ) {
    		strRet = ShortLocation( bundle.getLocation() );
    	}
    	
    	return strRet;
    }
    
    public static String getHeader(Bundle b, String name, String def) {
        String s = b != null
          ? (String)b.getHeaders().get(name)
          : def;

        return s;
      }

    static String ShortLocation( String location )
    {
    	int index	=	location.lastIndexOf( "/" );
    	
    	if( location.endsWith( "/" ) ) {
    		index	= location.lastIndexOf( "/" , index - 1 );
    	}
    	
    	if( index == -1 ){
    		index	=	location.lastIndexOf( "\\" );
    	}
    	
    	if( index != -1 ){
    		return location.substring( index + 1 );
    	}
    	
    	return location;
    }
    
    public String[] GetBundleList()
    {
    	String[] bundleNames	=	null;
    	Bundle[] bundles = _bundleContext.getBundles();
    	    	
    	for( int i = 0; i < bundles.length ; i++ )
    	{
    		//bundleNames[i]	=	null;
    		bundleNames[i]	=	"test";//GetBundleName( bundles[i] );
    		System.out.println( "Bundle List #" + i + " : " + bundleNames[i] );
    	}
    	
    	return bundleNames;
    }
    
	protected Bundle[] getBundleArray() {

	    if(_bundles == null) {
	    	_bundles = getAndSortBundles();
	    }

	    return _bundles;
	  }

	protected Bundle[] getAndSortBundles() {
	    Bundle[] 	bundles = 	_bundleContext.getBundles();
	    SortedSet 	set 	= 	new TreeSet(g_bundleIdComparator);
	    for(int i = 0; i < bundles.length; i++) {
	      set.add(bundles[i]);
	    }

	    set.toArray( bundles );    

	    return bundles;
	  }
	
	

	public static class BundleIdComparator implements Comparator {
		public int compare(Object o1, Object o2) {
			Bundle b1 = (Bundle)o1;
			Bundle b2 = (Bundle)o2;

			return (int)(b1.getBundleId() - b2.getBundleId());
	    }

	    public boolean equals(Object obj) {
	    	return obj.getClass().equals(BundleIdComparator.class);
	    }
	}
}
